package cn.wzut.edut.controller;

import cn.wzut.edut.dao.mapper.PtyStuMapper;
import cn.wzut.edut.dao.mapper.PtyTeacherMapper;
import cn.wzut.edut.dao.mapper.SysUserMapper;
import cn.wzut.edut.dao.pojo.table.*;
import cn.wzut.edut.jwt.PassToken;
import cn.wzut.edut.pojo.JsonResult;
import cn.wzut.edut.service.DeptService;
import cn.wzut.edut.service.UserService;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;

/**
 * 用户控制层
 * by 叶庭辉
 */
@Validated
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    DeptService deptService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private PtyTeacherMapper ptyTeacherMapper;

    @Autowired
    private PtyStuMapper ptyStuMapper;

    /**
     * 新增用户请求
     * @param userName
     * @param realName
     * @param deptId
     * @param sex
     * @param phone
     * @param password
     * @param type
     * @return
     */
    @PostMapping("/create")
    public JsonResult createUser(@RequestParam(value = "user_name") @Pattern(regexp = "\\d{11}", message = "用户名错误") @NotNull(message = "用户名不能为空") String userName,
                                 @RequestParam(value = "real_name") @Pattern(regexp = "[\\u4e00-\\u9fa5]{2,6}", message = "真实姓名错误") @NotNull(message = "真实姓名不能为空") String realName,
                                 @RequestParam(value = "dept") @Pattern(regexp = "^\\d*$", message = "组织id错误") String deptId,
                                 @RequestParam(value = "sex") @Pattern(regexp = "[男女]{1}", message = "性别错误") @NotNull(message = "性别不能为空") String sex,
                                 @RequestParam(value = "phone") @Pattern(regexp = "\\d{11}", message = "手机号错误") @NotNull(message = "手机号不能为空") String phone,
                                 @RequestParam(value = "password") @Pattern(regexp = "[a-zA-Z0-9-*/+.~!@#$%^&*()]{6,20}$", message = "密码错误") @NotNull(message = "密码不能为空") String password,
                                 @RequestParam(value = "type") @Pattern(regexp = "^(student|teacher)$", message = "用户类型错误") @NotNull(message = "用户类型不能为空") String type){

        return new JsonResult(userService.createUser(userName, realName, deptId, sex, phone, password, type));
    }

    /**
     * 删除用户请求
     * @param delUserIds
     * @param delFlag 标记删除{true:删除|false:标记}
     * @return
     */
    @PostMapping("/delete")
    public JsonResult deleteUser(@RequestParam(value = "del_array") @NotNull String[] delUserIds,
                                 @RequestParam(value = "del_flag") @NotNull boolean delFlag){
        return new JsonResult(userService.deleteUser(delUserIds, delFlag));
    }

    /**
     * 更新用户信息请求
     * @param realName
     * @param deptId
     * @param phone
     * @param userId
     * @return
     */
    @PostMapping("/update")
    public JsonResult updateUser(@RequestParam(value = "user_name") @Pattern(regexp = "\\d{11}", message = "用户名错误") @NotNull String userName,
                                 @RequestParam(value = "real_name") @Pattern(regexp = "[\\u4e00-\\u9fa5]{2,6}", message = "真实姓名错误") @NotNull String realName,
                                 @RequestParam(value = "dept") @NotNull String deptId,
                                 @RequestParam(value = "phone") @Pattern(regexp = "\\d{11}", message = "手机号错误") @NotNull String phone,
                                 @RequestParam(value = "id") @NotNull String userId){
        return new JsonResult(userService.updateUser(userName, realName, deptId, phone, userId));
    }

    /**
     * 重置用户密码请求
     * @param userId
     * @return
     */
    @GetMapping("/update/pwd")
    public JsonResult resetUserPassword(@RequestParam(value = "id") @NotNull String userId){
        return new JsonResult(userService.resetUserPassword(userId));
    }

    /**
     * 更新用户赋予的角色请求
     * @param userId
     * @param addRoles
     * @param delRoles
     * @return
     */
    @GetMapping("/update/role")
    public JsonResult updateRoleByUser(@RequestParam(value = "id") @NotNull String userId,
                                       @RequestParam(value = "add_roles") @NotNull String[] addRoles,
                                       @RequestParam(value = "del_roles") @NotNull String[] delRoles){
        return new JsonResult(userService.getRoleByUser(userId));
    }

    /**
     * 获取用户列表请求
     * @param type
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/list")
    public JsonResult getUserByType(@RequestParam(value = "type") @Pattern(regexp = "^(student|teacher)$", message = "用户类型错误") @NotNull String type,
                                    @RequestParam(value = "pagenum") @NotNull long current,
                                    @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getUserByType(type, current, size));
    }

    /**
     * 获取当前班级的学生列表请求
     * @param classId
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/list_by_class")
    public JsonResult getUserByClass(@RequestParam(value = "parent_dept_id") @NotNull String classId,
                                     @RequestParam(value = "pagenum") @NotNull long current,
                                     @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getUserByClass(classId, current, size));
    }

    /**
     * 获取当前组织指定名称的学生列表请求
     * @param realName
     * @param deptId
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/list_by_name_dept")
    public JsonResult getUserByNameAndDept(@RequestParam(value = "real_name") @Pattern(regexp = "[\\u4e00-\\u9fa5]{2,6}", message = "真实姓名错误") @NotNull String realName,
                                           @RequestParam(value = "parent_dept_id") @NotNull String deptId,
                                           @RequestParam(value = "pagenum") @NotNull long current,
                                           @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getUserByNameAndDept(realName, deptId, current, size));
    }

    /**
     * 根据用户真实姓名获取用户列表请求
     * @param name
     * @param type
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/name")
    public JsonResult getUserByName(@RequestParam(value = "real_name") @Pattern(regexp = "[\\u4e00-\\u9fa5]{2,6}", message = "真实姓名错误") @NotNull String name,
                                    @RequestParam(value = "type") @Pattern(regexp = "^(student|teacher)$", message = "用户类型错误") @NotNull String type,
                                    @RequestParam(value = "pagenum") @NotNull long current,
                                    @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getUserByName(name, type, current, size));
    }

    /**
     * 根据组织名获取用户列表请求
     * @param deptId
     * @param type
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/dept")
    public JsonResult getUserByDept(@RequestParam(value = "dept") @NotNull String deptId,
                                    @RequestParam(value = "type") @Pattern(regexp = "^(student|teacher)$", message = "用户类型错误") @NotNull String type,
                                    @RequestParam(value = "pagenum") @NotNull long current,
                                    @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getUserByDept(deptId, type, current, size));
    }

    /**
     * 根据用户真实姓名查询组织内用户列表请求
     * @param deptId
     * @param realName
     * @param type
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/dept/name")
    public JsonResult getUserByDeptAndName(@RequestParam(value = "dept") @NotNull String deptId,
                                           @RequestParam(value = "real_name") @Pattern(regexp = "[\\u4e00-\\u9fa5]{2,6}", message = "真实姓名错误") @NotNull String realName,
                                           @RequestParam(value = "type") @Pattern(regexp = "^(student|teacher)$", message = "用户类型错误") @NotNull String type,
                                           @RequestParam(value = "pagenum") @NotNull long current,
                                           @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getUserByDeptAndName(deptId, realName, type, current, size));
    }

    /**
     * 根据用户id获取用户信息请求
     * @param userId
     * @return
     */
    @GetMapping("/get/id")
    public JsonResult getUserInfoById(@RequestParam(value = "id") @NotNull String userId){
        return new JsonResult(userService.getUserInfoById(userId));
    }

    /**
     * 根据用户id获取用户所赋予的角色分页列表请求
     * @param userId
     * @param current
     * @param size
     * @return
     */
    @GetMapping("/get/role")
    public JsonResult getRoleByUser(@RequestParam(value = "id") @NotNull String userId,
                                    @RequestParam(value = "pagenum") @NotNull long current,
                                    @RequestParam(value = "pagesize") @NotNull long size){
        return new JsonResult(userService.getRoleByUser(userId, current, size));
    }

    /**
     * 根据用户id获取用户所赋予的角色列表请求
     * @param userId
     * @return
     */
    @GetMapping("/get/roles")
    public JsonResult getRoleByUser(@RequestParam(value = "id") @NotNull String userId){
        return new JsonResult(userService.getRoleByUser(userId));
    }

    /**
     * 导出用户信息excel请求
     * @param response
     * @throws Exception
     */
    @PassToken
    @GetMapping("/get/exportExcel")
    public void exportExcel(@NotNull HttpServletResponse response) throws Exception{
        // 文件名含中文需要转码
        String fileName = URLEncoder.encode("用户信息.xlsx", StandardCharsets.UTF_8.toString());
        // 设置响应格式
        response.setContentType("application/vnd.ms-excel;chartset=utf-8"); //文件扩展名为excel格式
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName); //触发文件名为filename的“另存为”对话框

        // 打包Excel数据
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

        WriteSheet writeSheet = EasyExcel.writerSheet(0, "学生信息").head(StudentInf.class).build();
        excelWriter.write((Collection<?>) userService.getUserByType("student").get("sysUserList"), writeSheet);
        writeSheet = EasyExcel.writerSheet(1, "教师信息").head(TeacherInf.class).build();
        excelWriter.write((Collection<?>) userService.getUserByType("teacher").get("sysUserList"), writeSheet);
        //千万别忘记finish 会帮忙关闭流
        excelWriter.finish();
    }

    /**
     * 下载模板excel请求
     * @param response
     * @throws Exception
     */
    @PassToken
    @GetMapping("/get/exportTemplate")
    public void exportTemplate(@NotNull HttpServletResponse response) throws Exception{
        // 文件名含中文需要转码
        String fileName = URLEncoder.encode("用户信息.xlsx", StandardCharsets.UTF_8.toString());
        // 设置响应格式
        response.setContentType("application/vnd.ms-excel;chartset=utf-8"); //文件扩展名为excel格式
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName); //触发文件名为filename的“另存为”对话框

        // 打包Excel数据
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

        WriteSheet writeSheet = EasyExcel.writerSheet(0, "学生信息").head(InfStudent.class).build();
        excelWriter.write((Collection<?>) Arrays.asList(new InfStudent(null, "20219111300", "学生甲", "0",
                "男", "1xxxxxxxxxx", "1", "(说明：这是用例记录)", null, null)), writeSheet);
        writeSheet = EasyExcel.writerSheet(1, "教师信息").head(InfTeacher.class).build();
        excelWriter.write((Collection<?>) Arrays.asList(new InfTeacher(null, "20219111300", "老师甲", "0",
                "男", "1xxxxxxxxxx", "1", "(说明：这是用例记录)", null)), writeSheet);
        writeSheet = EasyExcel.writerSheet(2, "组织对应表").head(SysDept.class).build();
        excelWriter.write((Collection<?>) deptService.getCollegeAndClass().get("sysDeptList"), writeSheet);
        //千万别忘记finish 会帮忙关闭流
        excelWriter.finish();
    }

    /**
     * 导入用户信息excel请求
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/create/importExcel")
    public JsonResult importData(@RequestParam("file") @NotNull MultipartFile file) throws IOException {
        if (file == null) new JsonResult(-1, "导入数据失败");

        ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build();
        StudentInfListener listener1 = new StudentInfListener();
        TeacherInfListener listener2 = new TeacherInfListener();
        // 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener
        // readSheet参数设置读取sheet的序号
        ReadSheet readSheet1 =
                EasyExcel.readSheet(0).headRowNumber(2).head(InfStudent.class).registerReadListener(listener1).build();
        ReadSheet readSheet2 =
                EasyExcel.readSheet(1).headRowNumber(2).head(InfTeacher.class).registerReadListener(listener2).build();
        // 这里注意 一定要把sheet1 sheet2 一起传进去，不然有个问题就是03版的excel 会读取多次，浪费性能
        System.out.println(excelReader.read(readSheet1,readSheet2));
        sysUserMapper.insertBatchSomeColumn(listener1.getSysUsers());
        ptyStuMapper.insertBatchSomeColumn(listener1.getPtyStus());
        sysUserMapper.insertBatchSomeColumn(listener2.getSysUsers());
        ptyTeacherMapper.insertBatchSomeColumn(listener2.getPtyTeachers());
        // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
        excelReader.finish();
        return new JsonResult("导入数据成功");
    }

}
